<template>
    <div class="containerr" style="text-align: center; align-content: center;">
        <el-icon class="el-icon--upload" style="font-size: 50px;"><upload-filled /></el-icon>
        <!-- <div class="el-upload__text" style="font-size: 20px;" @click="triggerFileInput">
            Drop file here or
            <em class="clickUploadEm">click to upload</em>
            <div style="color:orangered;"> (only support picture)</div>
        </div> -->
        <div class="el-upload__text" style="font-size: 20px;" @click="triggerFileInput">
            拖拽文件到这里 或者
            <em class="clickUploadEm">点击上传</em>
            <div style="color:orangered;"> (目前只支持照片，单个照片大小不超过10MB)</div>
        </div>
    </div>
    <div>
        <!-- <input type="file" multiple webkitdirectory mozdirectory odirectory> -->
        <!-- <input type="file" multiple> -->
        <input type="file" @change="handleFileSelect" multiple ref="fileInput" style="display: none;" />
    </div>
    <div>
        <el-switch v-model="autoUpload" class="ml-2" inline-prompt
            style="--el-switch-on-color: #13ce66; --el-switch-off-color: #ff4949" active-text="自动上传"
            inactive-text="不自动上传" @change="handleSwitchChange" />
    </div>
    <el-table :data="fileDataList" style="width: 100%">
        <el-table-column type="selection" width="55" />
        <el-table-column label="序号" type="index" width="55" :index="indexMethod" />
        <el-table-column label="文件名" prop="name" width="150" show-overflow-tooltip>
            <template #default="scope">
                <span>{{ scope.row.name }}</span>
            </template>
        </el-table-column>
        <el-table-column label="文件" prop="imageSrc" width="150">
            <template #default="scope">
                <el-image style="width: 100px; height: 100px; z-index: 2000;" :src="scope.row.imageSrc" :zoom-rate="1.2"
                    :max-scale="7" :min-scale="0.2" :preview-src-list="scope.row.previewSrcList" :initial-index="4"
                    fit="cover" :preview-teleported="true" />
            </template>
        </el-table-column>
        <el-table-column label="文件大小" prop="size" width="110">
            <template #default="scope">
                <span>{{ formatFileSize(scope.row.size) }}</span>
            </template>
        </el-table-column>
        <el-table-column label="上传进度" prop="process" width="450">
            <template #default="scope">
                <el-progress :text-inside="true" :stroke-width="22" :percentage="scope.row.process" status="success"
                    style="z-index: 1;" />
            </template>
        </el-table-column>
        <el-table-column label="后台处理结果" prop="status" width="145">
            <template #default="scope">
                <el-button :type="getBackendHandleResultType(scope.row.status)" size="small" :disabled="true">
                    {{ getBackendHandleResult(scope.row.status) }}</el-button>
            </template>
        </el-table-column>
        <el-table-column label="失败原因" prop="failMsg" width="195" show-overflow-tooltip>
            <template #default="scope">
                <span>{{ scope.row.failMsg }}</span>
            </template>
        </el-table-column>
        <el-table-column label="操作" width="200">
            <template #default="scope">
                <el-button type="primary" @click="manualUploadMode(new Array(scope.row))">上传</el-button>
                <el-button type="primary" :icon="Delete" @click="cancelUpload(scope.row, scope.$index)" />
                <!-- <template #default="scope"> -->
                <!-- <el-popconfirm width="220" confirm-button-text="确定" cancel-button-text="取消" :icon="InfoFilled"
                    icon-color="#626AEF" title="确定取消上传么？" @confirm="cancelUpload(scope.row)">
                    <template #reference>
                        <el-button type="primary" :icon="Delete" />
                    </template>
    </el-popconfirm> -->
                <!-- </template> -->
            </template>
        </el-table-column>
    </el-table>

</template>
<script setup lang='ts'>
import { ref, reactive, onMounted } from 'vue'
import { showErrorMsg, showSuccessMsg, indexMethod } from '@/api/common';
import { Delete } from '@element-plus/icons-vue'
import { fileUpload } from "@/api/file/file";
import { formatFileSize } from '@/utils/fileSize';
import type { ApiResponse } from '@/api/common';
import type { FileUploadData, FileDataSend, FileData } from '@/api/file/file';
const autoUpload = ref<boolean>(false)
const fileInput = ref<HTMLInputElement | null>(null);
let fileDataList = ref<FileUploadData[]>([])
const getNewFileData = (file: File) => {
    const newFileData = reactive<FileUploadData>({
        file: file,
        name: file.name,
        previewSrcList: [],
        imageSrc: '',
        size: file.size,
        process: 0,
        abortController: new AbortController(),
        status: 0,
        failMsg: '',
    });
    // 显示选择的图片
    const reader = new FileReader();
    reader.onload = (e) => {
        if (e.target?.result) {
            newFileData.imageSrc = e.target.result as string;
            newFileData.previewSrcList.push(newFileData.imageSrc)
        }
    };
    // 以DataURL的形式读取文件:
    reader.readAsDataURL(newFileData.file as File);
    return newFileData;
}
const readDirectory = (reader: FileSystemDirectoryReader): (Promise<void>) => {
    return new Promise((resolve) => {
        reader.readEntries((entries) => {
            entries.forEach((entry) => {
                if (entry.isDirectory) {
                    // 递归读取子文件夹
                    readDirectory((entry as FileSystemDirectoryEntry).createReader());
                } else if (entry.isFile) {
                    (entry as FileSystemFileEntry).file((file: File) => {
                        addFile(file);
                    });
                }
            });
        });
    })
}
const autoUploadMode = (fileList: FileUploadData[]) => {
    setTimeout(() => {
        doUpload(fileList.filter(r => r.process == 0 || r.status == 0));
    }, 500);
}
const manualUploadMode = (fileList: FileUploadData[]) => {
    return doUpload(fileList.filter(r => r.process == 0 || r.status == 2));
}
// 原先的upload方法，一次上传所有，没控制并发请求数量
const doUploadOrigin = (fileList: FileUploadData[]) => {
    for (const fileData of fileList) {
        fileData.abortController = new AbortController();
        // 映射 fileDataList 以创建一个新的数组，只包含我们想要发送到后端的数据
        const dataToSend = reactive<FileDataSend>({
            file: fileData.file,
            name: fileData.name,
            size: fileData.size,
        })
        const response: Promise<ApiResponse<string>> = fileUpload(dataToSend, (percentCompleted) => {
            fileData.process = percentCompleted;
        }, fileData.abortController);
        response.then((res: ApiResponse<string>) => {
            if (res) {
                if (res.status != 200) {
                    fileData.status = 2;
                    fileData.failMsg = res.msg;
                    showErrorMsg(res.msg);
                } else {
                    // setTimeout(() => {
                    fileData.process = 100;
                    fileData.status = 1;
                    showSuccessMsg(fileData.name + " 上传成功！");
                    // }, 2000);
                }
            }
        })
    }
}
const doUpload = async (fileList: FileUploadData[]) => {
    const uploadPromises = fileList.map(async (file) => {
        while (activeRequests.value >= maxConcurrentRequests) {
            await new Promise(resolve => setTimeout(resolve, 100)); // 等待直到有空闲的请求
        }
        activeRequests.value++;
        try {
            await doUploadSingleFile(file);
        } finally {
            activeRequests.value--;
        }
    });
    await Promise.all(uploadPromises);
    console.log('All files uploaded!');
}
// 当前正在上传的请求数
const activeRequests = ref(0);
// 最大上传请求并发数
const maxConcurrentRequests = 2;
const doUploadSingleFile = async (fileData: FileUploadData) => {
    fileData.abortController = new AbortController();
    // 映射 fileDataList 以创建一个新的数组，只包含我们想要发送到后端的数据
    const dataToSend = reactive<FileDataSend>({
        file: fileData.file,
        name: fileData.name,
        size: fileData.size,
    })
    const response: ApiResponse<string> = await fileUpload(dataToSend, (percentCompleted) => {
        fileData.process = percentCompleted;
    }, fileData.abortController);
    if (response) {
        if (response.status != 200) {
            fileData.status = 2;
            fileData.failMsg = response.msg;
            showErrorMsg(response.msg);
        } else {
            // 大于3M，延迟展示。线上看到大文件上传，卡在90+进度不动。
            if (fileData.size > 1024 * 1024 * 3) {
                setTimeout(() => {
                    fileData.process = 100;
                    fileData.status = 1;
                    showSuccessMsg(fileData.name + " 上传成功！");
                }, 850);
            } else {
                fileData.process = 100;
                fileData.status = 1;
                showSuccessMsg(fileData.name + " 上传成功！");
            }
        }
    }
}
onMounted(() => {
    const containerr = document.querySelector('.containerr') as HTMLDivElement;
    if (containerr) {
        containerr.ondragenter = (e) => {
            // 这三个事件都要去阻止它的默认行为
            // 为什么？ 因为默认div是不允许任何东西拖到它上面去的
            e.preventDefault();
        }
        // 一直悬停在这个div上面的事件
        containerr.ondragover = (e) => {
            e.preventDefault();
        }
        // 拖拽过来放手了
        containerr.ondrop = (e) => {
            e.preventDefault();
            //  e.dataTransfer?.items; 用这个可以拿到拖到上面的所有东西
            const items = e.dataTransfer?.items as DataTransferItemList;;
            for (const item of items) {
                const entry = item.webkitGetAsEntry();
                if (entry) {
                    if (entry?.isDirectory) {
                        // 递归读取文件夹内的所有文件
                        readDirectory((entry as FileSystemDirectoryEntry).createReader());
                        // // 获取文件夹的读取器
                        // const reader = (entry as FileSystemDirectoryEntry).createReader();
                        // // 读取文件夹下的子文件和子文件夹
                        // reader.readEntries((entries) => {
                        //     console.log(entries);
                        // })
                    } else {
                        (entry as FileSystemFileEntry).file((file: File) => {
                            addFile(file);
                        });
                    }
                }
            }
            if (autoUpload.value) {
                autoUploadMode(fileDataList.value);
            }
        }
    } else {
        console.error('Element with class "containerr" not found');
    }
})
const addFile = (file: File) => {
    // 检查文件类型是否为图片
    if (file.type.startsWith('image/')) {
        if (file.size > 10 * 1024 * 1024) {
            showErrorMsg("图片大小超过最大限制（10MB），将被自动移除！")
        } else {
            fileDataList.value.push(getNewFileData(file));
        }
    } else {
        showErrorMsg("只支持上传图片，非图片类型的文件将被自动移除！")
    }
}
// 选择文件时触发
const handleFileSelect = (event: Event) => {
    const target = event.target as HTMLInputElement;
    if (target.files) {
        for (const file of target.files) {
            addFile(file);
        }
        if (autoUpload.value) {
            autoUploadMode(fileDataList.value);
        }
    }
}
// 触发文件输入框点击事件
function triggerFileInput() {
    if (fileInput.value) {
        fileInput.value.click();
    }
}
// 取消上传
const cancelUpload = (fileData: FileUploadData, index: number) => {
    if (fileData.abortController) {
        fileData.abortController.abort();
        // fileData.abortController = undefined;
        fileData.abortController = null;
    }
    if (fileData) {
        fileDataList.value.splice(index, 1);
    }
}
const getBackendHandleResult = (status: number) => {
    switch (status) {
        case 0: return "正在处理";
        case 1: return "成功";
        case 2: return "失败";
    }
}
const getBackendHandleResultType = (status: number) => {
    switch (status) {
        case 0: return "primary";
        case 1: return "success";
        case 2: return "danger";
        default: return 'primary';
    }
}
const handleSwitchChange = (val: boolean) => {
    if (val) {
        autoUploadMode(fileDataList.value)
    }
}
</script>
<style scoped>
.containerr {
    height: 200px;
    border: 1px solid black;
}

.clickUploadEm {
    color: rgb(81, 167, 255);
    cursor: pointer;
    transition: cursor 0.3s ease-in-out;
}
</style>